package de.thm.exa.tests;

import de.thm.exa.algos.ChainedHash;
import de.thm.exa.helpers.FileReader;
import de.thm.exa.helpers.FileWriter;
import de.thm.exa.helpers.Hash;
import de.thm.exa.holders.Page;
import de.thm.exa.interfaces.TestInterface;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class ChainedTest implements TestInterface
{
    
    @Override
    public void test() throws IOException
    {
        BufferedReader reader = new BufferedReader( new InputStreamReader(System.in) );
        
        int input;
        
        while(true)
        {
            printInput();
            try
            {
                input = Integer.parseInt( reader.readLine() );
            } catch(NumberFormatException e) {
                printError();
                continue;
            }
            
        	if( input == 8 ) {
                chainedTestAll();
                reader.close();
                break;
            } else if ( input < 8 && input > 0 ) {
                System.out.println( "Algorithm: " + Hash.toString(input - 1) );
                ArrayList<Page> pages = readPages();

                File output = new File(DEST_FILE);
                FileWriter.writeHeader( output );

                ChainedHash hasher = new ChainedHash(input - 1);
                chainedTest(hasher, pages, output);
                
                break;
            } else if(input == 9) {
                reader.close();
                return;
            } else {
                printError();
            }
        }
        reader.close();
    }
    
    private void printInput()
    {
        System.out.println(
                  "Enter a number:\n"
                + "  1: " + Hash.toString(0) + "\n"
                + "  2: " + Hash.toString(1) + "\n"
                + "  3: " + Hash.toString(2) + "\n"
                + "  4: " + Hash.toString(3) + "\n"
                + "  5: " + Hash.toString(4) + "\n"
                + "  6: " + Hash.toString(5) + "\n"
                + "  7: " + Hash.toString(6) + "\n"
                + "  8: All Tests\n"
                + "  9: Close Program\n");
    }
    
    private void printError()
    {
        System.out.println("This was not a correct input.");
    }
    
    private void chainedTest(ChainedHash hasher, ArrayList<Page> pages, File output) throws IOException
    { 
        hasher.setElapsedTime(0);
        long elapsedTime = 0;
        for(Page page : pages)
        {
            hasher.insert(page);
            elapsedTime += hasher.getElapsedTime();
        }
        hasher.setElapsedTime(elapsedTime);
        System.out.println( hasher.toString() );
        
        hasher.printFile( output );
    }
    
    private void chainedTestAll() throws IOException
    {
        ArrayList<Page> pages = readPages();
        File output = new File(DEST_FILE);
        FileWriter.writeHeader( output );

        int k = 1;
        for(int i = 0 ; i < Hash.FUNCTION_COUNT ; i++)
        {
            ChainedHash hasher = new ChainedHash(i);
            chainedTest(hasher, pages, output);
            
            System.out.println("Test " + k + "/" + Hash.FUNCTION_COUNT + " completed\n" );
            k++;
        }
    }
    
    private ArrayList<Page> readPages() throws IOException
    {
        File dir = new File(Hash.PATH);
        
        File[] files = dir.listFiles();


        int fileIndex = 1;
        ArrayList<Page> pages = new ArrayList<>();
        for( File file : files )
        {
        	int files_count = MAX_FILES < files.length ? MAX_FILES : files.length;
            System.out.println("Reading File: " + file.getName() + "[" + fileIndex + "/" + files_count + "]");
            pages.addAll( FileReader.read( file ) );
            fileIndex++;
            if ( fileIndex > MAX_FILES )
            {
            	break;
            }
        }
        return pages;
    }
}
